LINQ inleiding
Home

LINQ inleiding

LINQ inleiding

LINQ stelt programmeurs queries te maken als eerste klas SQL programmeurs maar dan wel in C # en Visual Basic.

Bouwstenen van LINQ

De twee fundamentele bouwstenen van LINQ zijn elementen en reeksen.

Een reeks kan van worden gezien als een lijst van items, en elk item in de lijst als een element. Een reeks is een instantie van een klasse die de IEnumerable <T> interface implementeert.

Nemen we een reeks van nummers die we als een array declaren int[] leeftijden = {50, 1, 11, 2, 28, 2, 13, 25, 50}. de variabele leeeftijden stelt een reeks voor waarvan elke int in de array een individueel element is.

Een reeks kan een lokale reeks van objecten in het geheugen zijn of een externe reeks, zoals een SQL Server-database. Die externe gegevensbronnen (bijvoorbeeld SQL Server), deze externe reeksen worden ook door een IQueryable <T> interface voorgesteld.

Queries, of meer specifiek query operatoren, zijn van toepassing op een invoerreeks en produceren één of meerdere output waarden. Deze outputwaarde kan een getransformeerde versie van de inputsequentie zijn, namelijk een uitvoer sequentie of enkele scalaire waarde zoals een telling van het aantal elementen in de ingevoerde sequentie.

Query's die worden uitgevoerd op de lokale sequenties staan ​​bekend als lokale queries of LINQ-to-objects queries.

Er zijn een hele reeks van query-operatoren die geïmplementeerd worden als extensie-methoden in de statische System.Linq.Enumerable klasse. Deze set van query's zijn de standaard query.

Een belangrijk ding om op te merken bij het gebruik van query's is dat ze de input reeks niet veranderen. In plaats van de input reeks te veranderen stuurt de query operator een nieuwe reeks (of scalaire waarde) terug.

Scalaire retourwaarden en outputreeksen

Een query operator retoruneert een outputreeks of een scalaire waarde. In de volgende code wordt de ingevoerde sequentie leeftijden bewerkt, eerst door de Count queryoperator, dat een enkele scalaire waarde retourneert, namelijk het aantal elementen in de ingevoerde sequentie. Vervolgens wordt dezelfde inputreeks bewerkt met de Distinct queryoperator, die een nieuwe uitvoersequentie met de elementen uit de ingevoerde sequentie produceert, maar met de dubbele elementen eruit verwijderd.

int[] leeftijden = { 50, 1, 11, 2, 28, 2, 13, 25, 50 };
// scalar return value
int numberOfElements = leeftijden.Count();
Console.WriteLine("Aantal leeftijden {0}", numberOfElements);

// Output sequence return value
IEnumerable < int > verschillendeLeeftijden = leeftijden.Distinct();

Console.WriteLine("Verschillende leeftijden in de outputreeks: ");
foreach (int leeftijd in leeftijden)
{
    Console.WriteLine(leeftijd);
}

Als we de code uitvoeren krijgen we het volgende:

Scalaire retourwaarden en outputreeksen
Scalaire retourwaarden en outputreeksen

Uitgestelde uitvoering

De meeste queries worden niet onmiddellijk uitgevoerd. De uitvoering ervan wordt uitgesteld tot een later tijdstip in de uitvoering van het programma. Dit betekent dat de zoekopdracht niet wordt uitgevoerd wanneer ze wordt gemaakt, maar wanneer ze wordt gebruikt, bijvoorbeeld wanneer ze opgesomd wordt.

Uitgestelde uitvoering betekent dat de ingevoerde sequentie kan worden gewijzigd nadat de query is geconstrueerd, maar wel voordat de query wordt uitgevoerd. In de volgende code wordt de ingevoerde sequentie gewijzigd nadat de query is geconstrueerd, maar voordat deze wordt uitgevoerd.

int[] leeftijden = { 50, 1, 11, 2, 28, 2, 13, 25, 50 };
// scalar return value
// construct the query
IEnumerable<int> ouderDan11 = leeftijden.Where(x => x > 10);

// Change the third element
leeftijden[2] = 100;
// At this point the query has been created but not executed
Console.WriteLine("Ouder dan 11: ");
foreach (int leeftijd in ouderDan11)
{
    Console.WriteLine(leeftijd);
}

De query wordt niet uitgevoerd totdat de foreach wordt uitgevoerd. De resultaten van het uitvoeren van deze code zijn:

LINQ Deferred Execution
LINQ Deferred Execution

Merk op dat de waarde 100 is opgenomen in de resultaten, niettegenstaande het derde element op het moment dat de query werd gemaakt, nog steeds de waarde van 11 had.

De queries die een een scalaire waarde retourneren (of een enkel element van de ingevoerde sequentie) zoals Count, Min en Last werken niet op deze uitgestelde executie manier. Dus bij het gebruik van operatoren zoals Count zal de queryonmiddellijk worden uitgevoerd, en niet uitgesteld.

Een aantal van de conversie operatoren worden ook onmiddellijk uitgevoerd, zoals ToList, ToArray, ToLookup en ToDictionary.

In de volgende code wordt de leeftijden matrix worden gewijzigd net zoals in het voorgaande voorbeeld. Maar in dit voorbeeld werd de query op het moment dat de wijziging plaatsvindt reeds uitgevoerd vanwege de extra ToArray() operator. De wijziging zal niet worden opgenomen in de foreach.

int[] leeftijden = { 50, 1, 11, 2, 28, 2, 13, 25, 50 };
// scalar return value
// construct the query
IEnumerable<int> ouderDan11 = leeftijden.Where(x => x > 10).ToArray();

// Change the third element
leeftijden[2] = 100;
// At this point the query has been created and 
// executed because of the ToArray() operator
Console.WriteLine("Ouder dan 11: ");
foreach (int leeftijd in ouderDan11)
{
    Console.WriteLine(leeftijd);
}
LINQ Immediate Execution
LINQ Immediate Execution

De waarde 100 is hier niet meer aanwezig, omdat de inputreeks werd gewijzigd nadat de query is uitgevoerd door de ToArray() operator.

Lambda expressies in query operatoren

Sommige query's accepteren anonieme functies als argument waarmee je aangepaste logica aan de query kan doorgeven. Deze aangepaste logica kan je aan de query doorgeven door middel van een lambda-expressie.

De leeftijden.Where (x => x > 11) code in het voorgaande codevoorbeeld is een voorbeeld van een query operator waaraan een anonieme functie wordt doorgegeven. De lambda-expressie x => x > 11 zorgt ervoor dat alleen de elementen (integers in dit geval) die groter zijn dan 11 gertourneerd worden.

Wanneer een queryoperator een lambda-expressie als argument meekrijgt, wordt de logica van de lambda-expressie op elk element van de invoer-sequentie toegepast.

Het type lambda expressie, die wordt ingevoerd in een queryoperator, is afhankelijk van de taak die de queryoperator uitvoert. In de volgende figuur zien we de handtekening van de Where-query operator. Het inputelement int wordt voorzien en een bool moet worden teruggestuurd die bepaalt of het element wordt opgenomen in de uitvoer-sequentie.

Visual Studio toont de signatuur van de Where operator
Visual Studio toont de signatuur van de Where operator

In plaats van een lambda-expressie kan je een klassieke delegate, die verwijst naar een methode, gebruiken.

Geïnterpreteerde (interpreted) queries

Tot nu toe hebben we ons gericht op lokale queries. Lokale queries manipuleren IEnumerable<T> sequenties. Lokale queries zijn het resultaat van de uitgevoerde query's, die zijn gedefinieerd in de System.Linq.Enumerable klasse. Op die manier resulteert het uitvoeren van een lokale query in code die wordt gedefinieerd tijdens het compileren.

Geïnterpreteerde queries, aan de andere kant, beschrijven slechts de "vorm" van de query die wordt geïnterpreteerd tijdens runtime - vandaar de naam "geïnterpreteerd." Geïnterpreteerde queries manipuleren IQueryable<T> sequenties, en de LINQ operatoren worden omgezet naar methoden die gedefinieerd zijn in de System.Linq.Queryable klasse in plaats van de System.Linq.Enumerable klasse.

De lokale (IEnumerable<T>) queries bevatten de werkelijke implementatie van de query code die wordt uitgevoerd, terwijl de geïnterpreteerde queries (IQueryable <T>) niet. Bij geïnterpreteerde queries, is de werkelijke query code, die wordt uitgevoerd, gedefinieerd in een query provider. De query provider ontvangt de beschrijving van de query die moet worden uitgevoerd en voert de query vervolgens uit (bijvoorbeeld het uitvoeren van SQL op een database) en retourneert tenslotte het resultaat.

JI
2020-12-07 18:37:33